﻿using CodeFirstStoreFunctions;
using Kairos.Migrations;
using System.Collections.Generic;
using System.Data.Entity;
using System.Data.Entity.Core.Objects;
using System.Data.Entity.Infrastructure;
using System.Data.Entity.ModelConfiguration.Conventions;
using System.Data.Entity.Validation;
using System.Globalization;
using System.Linq;
using System.Reflection;

namespace Kairos.Models
{
    public class myContext : DbContext
    {
        static myContext()
        {
            Database.SetInitializer(new myCreateDatabaseIfNotExists());
        }
        public myContext()
            : base(Assembly.GetExecutingAssembly().GetName().Name)
        { }
        public DbSet<Document> Documents { get; set; }
        public DbSet<Graphe> Graphes { get; set; }
        public DbSet<Image> Images { get; set; }
        public DbSet<Mappage> Mappages { get; set; }
        public DbSet<MetaData1> MetaDatas1 { get; set; }
        public DbSet<MetaData2> MetaDatas2 { get; set; }
        public DbSet<Vtom> Vtoms { get; set; }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            //https://entityframework.codeplex.com/wikipage?title=Code%20First%20Annotations

            modelBuilder.Conventions.Add(
                new AttributeToColumnAnnotationConvention<CollationAttribute, string>(
                    Utilities.CollationAnnotationName,
                    (entityType, attributes) => attributes.Single().Name));

            // If a foreign key on the dependent entity is not nullable, 
            // then Code First sets cascade delete on the relationship. 
            // If a foreign key on the dependent entity is nullable, 
            // Code First does not set cascade delete on the relationship, 
            // and when the principal is deleted the foreign key will be set to null.

            modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();

            // Precedence is given to configuration through the fluent API 
            // followed by data annotations and then conventions.

            modelBuilder.Entity<Vtom>().Property(p => p.DocID).IsOptional();

            // https://codefirstfunctions.codeplex.com/

            modelBuilder.Conventions.Add(new FunctionsConvention<myContext>("dbo"));

            base.OnModelCreating(modelBuilder);
        }

        [DbFunction("myContext", "SearchGraphes")]
        public IQueryable<Graphe> SearchGraphes(string searchstring)
        {
            return ((IObjectContextAdapter)this).ObjectContext
                .CreateQuery<Graphe>(string.Format(CultureInfo.InvariantCulture, "[{0}].{1}", GetType().Name,
                    "[SearchGraphes](@searchstring)"), new ObjectParameter("searchstring", searchstring));
        }

        [DbFunction("myContext", "SearchDocuments")]
        public IQueryable<Document> SearchDocuments(string searchstring)
        {
            return ((IObjectContextAdapter)this).ObjectContext
                .CreateQuery<Document>(string.Format(CultureInfo.InvariantCulture, "[{0}].{1}", GetType().Name,
                    "[SearchDocuments](@searchstring)"), new ObjectParameter("searchstring", searchstring));
        }

#if DEBUG
        /// <remarks>
        /// Skip DbEntityValidationException during execution of the Seed method
        /// while inserting a Vtom.DocID null value in a required nullable field.
        /// </remarks>
        protected override DbEntityValidationResult ValidateEntity(DbEntityEntry entityEntry, IDictionary<object, object> items)
        {
            DbEntityValidationResult result = base.ValidateEntity(entityEntry, items);

            if (entityEntry.Entity.GetType() == typeof(Vtom) || entityEntry.Entity.GetType().BaseType == typeof(Vtom))
                foreach (var propertyValidationError in result.ValidationErrors.Where(e => e.PropertyName == "DocID").ToList())
                    result.ValidationErrors.Remove(propertyValidationError);

            return result;
        }
#endif
    }
}